<!DOCTYPE html>
<html>

<head>
  <title>横向树形图</title>

  <script type="text/javascript" src="http://d3js.org/d3.v5.min.js">
  </script>

  <meta name="keywords" content="keyword1,keyword2,keyword3">
  <meta name="description" content="this is my page">
  <meta name="content-type" content="text/html; charset=GBK">

  <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

</head>

<body>
  <svg width="1200" height="600"></svg>
  <script>
    //定义边界
    var marge = { top: 100, bottom: 0, left: 10, right: 0 };

    var svg = d3.select("svg");
    var width = svg.attr("width");
    var height = svg.attr("height");

    var g = svg.append("g")
      .attr("transform", "translate(" + marge.left + "," + marge.top + ")");

    var scale = svg.append("g")
      .attr("transform", "translate(" + marge.left + "," + marge.top + ")");
    //数据
    var dataset = {
      name: "中国",
      children: [
        {
          name: "浙江",
          children: [
            { name: "杭州", value: 100 },
            { name: "宁波", value: 100 },
            { name: "温州", value: 100 },
            { name: "绍兴", value: 100 }
          ]
        },
        {
          name: "广西",
          children: [
            {
              name: "桂林",
              children: [
                { name: "秀峰区", value: 100 },
                { name: "叠彩区", value: 100 },
                { name: "象山区", value: 100 },
                { name: "七星区", value: 100 }
              ]
            },
            { name: "南宁", value: 100 },
            { name: "柳州", value: 100 },
            { name: "防城港", value: 100 }
          ]
        },
        {
          name: "黑龙江",
          children: [
            { name: "哈尔滨", value: 100 },
            { name: "齐齐哈尔", value: 100 },
            { name: "牡丹江", value: 100 },
            { name: "大庆", value: 100 }
          ]
        },
        {
          name: "新疆",
          children:
            [
              { name: "乌鲁木齐" },
              { name: "克拉玛依" },
              { name: "吐鲁番" },
              { name: "哈密" }
            ]
        }
      ]
    };

    //创建一个hierarchy layout
    // d3.hierarchy层级布局，需要和tree生成器一起使用，来得到绘制树所需要的节点数据和边数据
    var hierarchyData = d3.hierarchy(dataset)
      .sum(function (d) {  //所有数据遍历
        return d.value;
      });

    console.log("data", dataset);
    console.log("hierarchyData", hierarchyData);

    //创建一个树状图
    var tree = d3.tree()
      .size([width - 100, height - 200]) //定义树的大小
      .separation(function (a, b) {
        return a.parent == b.parent ? 3 : 2;  //定义邻居节点的距离
      })

    //初始化树状图，也就是传入数据,并得到绘制树基本数据
    var treeData = tree(hierarchyData);
    console.log("treeData", treeData);
    //得到节点
    var nodes = treeData.descendants();  //得到所有的节点
    var links = treeData.links(); //得到所有的边

    //输出节点和边
    console.log("nodes:", nodes);
    console.log("links:", links);

    //创建一个水平贝塞尔生成曲线生成器
    var Bézier_curve_generator = d3.linkVertical()
      .x(function (d) { return d.x; })
      .y(function (d) { return d.y; });

    //有了节点和边集的数据后，我们就可以开始绘制了，
    //绘制边
    g.append("g")
      .selectAll("path")
      .data(links)
      .enter()
      .append("path")
      .attr("d", function (d) {
        var start = { x: d.source.x, y: d.source.y };
        var end = { x: d.target.x, y: d.target.y };
        return Bézier_curve_generator({ source: start, target: end }); //贝塞尔弧度
      })
      .attr("fill", "none")
      .attr("stroke", "yellow")
      .attr("stroke-width", 1);

    //绘制节点和文字
    //老规矩，先创建用以绘制每个节点和对应文字的分组<g>
    var gs = g.append("g")
      .selectAll("g")
      .data(nodes)
      .enter()
      .append("g")
      .attr("transform", function (d) {
        var cx = d.x;
        var cy = d.y;
        return "translate(" + cx + "," + cy + ")";
      });
    //绘制节点
    gs.append("circle")
      .attr("r", 6)
      .attr("fill", "white")
      .attr("stroke", "blue")
      .attr("stroke-width", 1);

    //文字
    gs.append("text")
      .attr("text-anchor", d => d.children ? "end" : "start")
      .attr("x", function (d) {
        // return -15;
      })
      .attr("y", function (d) {
        return d.children ? -15 : 27;
      })
      .text(function (d) {
        return d.data.name;
      })
      .attr("writing-mode", 'vertical-rl')//横排从上到下
      .attr("text-orientation", 'upright');
  </script>
</body>

</html>
